#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using UTable.Input;
using UTable.Input.MultiTouch;
using UTable.Objects.Handlers;

namespace UTable.Objects.Controls
{
    public class UToggleButton: ToggleButton, IControl
    {
        #region Constructors

        static UToggleButton()
        {
            UControlImpl.OverrideMetadata(typeof(UToggleButton));
            DefaultStyleKeyProperty.OverrideMetadata(typeof(UToggleButton), new FrameworkPropertyMetadata(typeof(UToggleButton)));
        }

        public UToggleButton()
        {
            this.VerticalContentAlignment = VerticalAlignment.Center;
            this.HorizontalContentAlignment = HorizontalAlignment.Center;
            InitializeIControlPart();

            DetectContactsHandler handler = new DetectContactsHandler();
            handler.NewContact += new ContactEventHandler(handler_NewContact);
            handler.NoContact += new ContactEventHandler(handler_NoContact);
            MultiTouchProcessor.Handlers.Add(handler);
            this.InputReceived += UButton_InputReceived;
        }

        #endregion

        #region Properties

        public Brush GlowBrush
        {
            get { return (Brush)GetValue(GlowBrushProperty); }
            set { SetValue(GlowBrushProperty, value); }
        }

        public static readonly DependencyProperty GlowBrushProperty =
            DependencyProperty.Register("GlowBrush", typeof(Brush), typeof(UToggleButton), new UIPropertyMetadata(new SolidColorBrush(Colors.White)));


        public Brush CheckMarkBrush
        {
            get { return (Brush)GetValue(CheckMarkBrushProperty); }
            set { SetValue(CheckMarkBrushProperty, value); }
        }

        public static readonly DependencyProperty CheckMarkBrushProperty =
            DependencyProperty.Register("CheckMarkBrush", typeof(Brush), typeof(UToggleButton), new UIPropertyMetadata(Brushes.White));


        #endregion

        #region Private Methods

        void handler_NoContact(FingerEventArgs args)
        {
            if (!this.IsEnabled)
                return;

            Point p = args.Position;
            this.IsPressed = false;
            if (args.EventType == FingerEventType.FINGER_UP_EVENT && p.X >= 0 && p.X <= this.ActualWidth && p.Y >= 0 && p.Y <= this.ActualHeight)
            {
                if (this.IsChecked == true)
                {
                    if (this.IsThreeState)
                    {
                        IsChecked = null;
                        RaiseIndeterminedEvent();
                    }
                    else
                    {
                        IsChecked = false;
                        RaiseUncheckEvent();
                    }
                }
                else if(this.IsChecked == null)
                {
                    IsChecked = false;
                    RaiseUncheckEvent();
                }
                else
                {
                    IsChecked = true;
                    RaiseCheckEvent();
                }
            }
        }

        void handler_NewContact(FingerEventArgs args)
        {
            if (!this.IsEnabled)
                return;

            this.IsPressed = true;
        }

        private void UButton_InputReceived(InputEventArgs args)
        {
            if (!this.IsEnabled)
                return;

            args.Handled = true;
        }

        void RaiseCheckEvent()
        {
            this.RaiseEvent(new RoutedEventArgs(ToggleButton.CheckedEvent));
        }

        void RaiseUncheckEvent()
        {
            this.RaiseEvent(new RoutedEventArgs(ToggleButton.UncheckedEvent));
        }

        void RaiseIndeterminedEvent()
        {
            this.RaiseEvent(new RoutedEventArgs(ToggleButton.IndeterminateEvent));
        }

        #endregion


		#region IControl Implementation
		
		#region Private Fields

        private ControlBaseImpl _impl;

        #endregion

		#region Private Methods

		private void InitializeIControlPart()
        {
			_impl = new ControlBaseImpl(this);
            _impl.GotFingerCapture += new UTable.Input.MultiTouch.FingerEventHandler(_impl_GotFingerCapture);
            _impl.LostFingerCapture += new UTable.Input.MultiTouch.FingerEventHandler(_impl_LostFingerCapture);
			this.InputReceived += new UTable.Input.InputEventHandler(_impl_InputReceived);
        }

        void _impl_InputReceived(UTable.Input.InputEventArgs args)
        {
			if (args is UTable.Input.MultiTouch.MultiTouchEventArgs)
				MultiTouchProcessor.RaiseMultiTouchEvent(args as UTable.Input.MultiTouch.MultiTouchEventArgs);
        }

        void _impl_LostFingerCapture(object sender, UTable.Input.MultiTouch.FingerEventArgs args)
        {
            if (LostFingerCapture != null)
                LostFingerCapture(sender, args);
        }

        void _impl_GotFingerCapture(object sender, UTable.Input.MultiTouch.FingerEventArgs args)
        {
            if (GotFingerCapture != null)
                GotFingerCapture(sender, args);
        }

        #endregion

        #region IControl Members

        public UTable.Objects.Controls.ControlInfo Info
        {
            get { return _impl.Info; }
        }
		
		public UTable.Objects.Handlers.MultiTouchProcessor MultiTouchProcessor 
		{ 
			get { return _impl.MultiTouchProcessor; } 
		}

        #endregion

        #region IVisualNode Members

        public String ID
        {
            get { return _impl.ID; }
        }

        public new double Width
        {
            get { return _impl.Width; }
            set { _impl.Width = value; }
        }

        public new double Height
        {
            get { return _impl.Height; }
            set { _impl.Height = value; }
        }

        public new bool IsHitTestVisible
        {
            get { return _impl.IsHitTestVisible; }
            set { _impl.IsHitTestVisible = value; }
        }

        #endregion

        #region IInputNode Members

        public void RaiseEvent(UTable.Input.InputEventArgs e)
        {
            if (InputReceived != null)
            {
                InputReceived(e);
            }
            OnInputReceived(e);
        }

        public virtual void OnInputReceived(UTable.Input.InputEventArgs args)
        {
            _impl.OnInputReceived(args);
        }

        public bool CaptureFinger(int fingerId)
        {
            return _impl.CaptureFinger(fingerId);
        }

        public bool UncaptureFinger(int fingerId)
        {
            return _impl.UncaptureFinger(fingerId);
        }

        public event UTable.Input.MultiTouch.FingerEventHandler GotFingerCapture;

        public event UTable.Input.MultiTouch.FingerEventHandler LostFingerCapture;

        public event UTable.Input.InputEventHandler InputReceived;

        #endregion
        #endregion
    }
}
